package com.tz.tools;

import com.tz.tools.constant.CommonConstants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * List常用工具
 *
 * @author zjc
 * @since 2023/1/5 9:16
 */
public class ListTools {

    /**
     * 返回空的集合
     *
     * @param <T> 泛型
     * @return 空集合
     */
    public static <T> List<T> emptyList() {
        return new ArrayList<>();
    }

    /**
     * 集合滤空
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 结果集
     */
    public static <T> List<T> filterNonNull(List<T> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 字符串集合过滤
     *
     * @param list 字符串集合
     * @return 结果集
     */
    public static List<String> filterNotBlank(List<String> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream()
                    .filter(StringUtils::isNotBlank).map(String::trim).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 集合去空格
     *
     * @param list 集合
     * @return 结果集
     */
    public static List<String> trim(List<String> list) {
        return map(list, StringUtils::trim);
    }

    /**
     * 字符串集合过滤并去重
     *
     * @param list 字符串集合
     * @return 结果集
     */
    public static List<String> filterNotBlankAndDistinct(List<String> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(StringUtils::isNotBlank)
                    .map(String::trim).distinct().collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 集合过滤
     *
     * @param list      集合
     * @param predicate 过滤函数
     * @param <T>       泛型
     * @return 结果集
     */
    public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).filter(predicate).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 集合转换
     *
     * @param list   集合
     * @param mapper 转换函数
     * @param <T>    集合泛型
     * @param <R>    转换泛型
     * @return 结果集
     */
    public static <T, R> List<R> map(List<T> list, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 集合转换 一对多平铺
     *
     * @param list   集合
     * @param mapper 转换函数
     * @param <T>    集合泛型
     * @param <R>    转换泛型
     * @return 结果集
     */
    public static <T, R> List<R> flatMap(List<T> list, Function<? super T, List<? extends R>> mapper) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull)
                    .map(mapper).filter(Objects::nonNull)
                    .flatMap(Collection::stream).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 集合转map
     *
     * @param list        集合
     * @param keyMapper   key映射函数
     * @param valueMapper 值映射函数
     * @param <T>         集合泛型
     * @param <K>         key泛型
     * @param <U>         value泛型
     * @return map
     */
    public static <T, K, U> Map<K, U> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,
                                            Function<? super T, ? extends U> valueMapper) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).collect(Collectors.toMap(keyMapper, valueMapper));
        }
        return new HashMap<>();
    }

    /**
     * 集合转map(带合并函数)
     *
     * @param list          集合
     * @param keyMapper     key映射函数
     * @param valueMapper   值映射函数
     * @param mergeFunction 合并函数
     * @param <T>           集合泛型
     * @param <K>           key泛型
     * @param <U>           value泛型
     * @return map
     */
    public static <T, K, U> Map<K, U> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,
                                            Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull)
                    .collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction));
        }
        return new HashMap<>();
    }

    /**
     * list分组
     *
     * @param list       集合
     * @param classifier 分组函数
     * @param <T>        泛型
     * @param <K>        key泛型
     * @return map
     */
    public static <T, K> Map<K, List<T>> group(List<T> list, Function<? super T, ? extends K> classifier) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream()
                    .filter(Objects::nonNull).collect(Collectors.groupingBy(classifier));
        }
        return new HashMap<>();
    }

    /**
     * list分组
     *
     * @param list      集合
     * @param keyFinder 分组key定义
     * @param <T>       传入源对象
     * @param <K>       key泛型
     * @param <V>       mapping之后的value
     * @return map
     */
    public static <T, K, V> Map<K, List<V>> groupMapping(List<T> list, Function<? super T, ? extends K> keyFinder,
                                                         Function<? super T, ? extends V> valueMapper) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull)
                    .collect(Collectors.groupingBy(keyFinder, Collectors.mapping(valueMapper, Collectors.toList())));
        }
        return new HashMap<>();
    }

    /**
     * list分组 且去重
     *
     * @param list      集合
     * @param keyFinder 分组key定义
     * @param <T>       传入源对象
     * @param <K>       key泛型
     * @param <V>       mapping之后的value
     * @return map
     */
    public static <T, K, V> Map<K, Set<V>> groupMappingSet(List<T> list, Function<? super T, ? extends K> keyFinder,
                                                           Function<? super T, ? extends V> valueMapper) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull)
                    .collect(Collectors.groupingBy(keyFinder, Collectors.mapping(valueMapper, Collectors.toSet())));
        }
        return new HashMap<>();
    }

    /**
     * 可变对象生成集合
     *
     * @param array 可变对象
     * @param <T>   泛型
     * @return 结果集
     */
    @SafeVarargs
    public static <T> List<T> asList(T... array) {
        if (ArrayUtils.isNotEmpty(array)) {
            return Arrays.stream(array).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 单个对象转集合
     *
     * @param t   对象
     * @param <T> 泛型
     * @return 结果集
     */
    public static <T> List<T> singletonList(T t) {
        List<T> list = new LinkedList<>();
        if (Objects.nonNull(t)) {
            list.add(t);
        }
        return list;
    }

    /**
     * list转数组
     *
     * @param list   集合
     * @param tClass 泛型class对象
     * @param <T>    泛型
     * @return 数组
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(List<T> list, Class<T> tClass) {
        if (CollectionUtils.isNotEmpty(list)) {
            T[] array = (T[]) Array.newInstance(tClass, list.size());
            // 赋值
            for (int i = 0; i < list.size(); i++) {
                array[i] = list.get(i);
            }
            return array;
        }
        return (T[]) Array.newInstance(tClass, 0);
    }

    /**
     * 集合去重(调用对象的equals方法)
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 结果集
     */
    public static <T> List<T> distinct(List<T> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 根据指定属性去重(调用对象的equals方法)
     *
     * @param list         集合
     * @param keyExtractor 获取属性的函数
     * @return 结果集
     */
    public static <T> List<T> distinct(List<T> list, Function<? super T, Object> keyExtractor) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().filter(Objects::nonNull).filter(distinctByKey(keyExtractor)).collect(Collectors.toList());
        }
        return emptyList();
    }

    /**
     * 根据对象的某个属性去重
     *
     * @param keyExtractor key提取函数
     * @return 断言结果
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>(16);
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 集合联合
     *
     * @param list1 集合1
     * @param list2 集合2
     * @param <T>   泛型
     * @return 结果集
     */
    public static <T> List<T> union(List<? extends T> list1, List<? extends T> list2) {
        List<T> list = new LinkedList<>();
        list.addAll(list1);
        list.addAll(list2);
        return list;
    }

    /**
     * 返回集合中第一个不为null的对象(optional版本)
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 对象
     */
    public static <T> Optional<T> single(List<T> list) {
        list = filterNonNull(list);
        if (CollectionUtils.isNotEmpty(list)) {
            return Optional.of(list.get(NumberUtils.INTEGER_ZERO));
        }

        return Optional.empty();
    }

    /**
     * 返回集合中第一个不为null的对象(null版本)
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 结果
     */
    public static <T> T singleObject(List<T> list) {
        list = filterNonNull(list);
        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(NumberUtils.INTEGER_ZERO);
        }

        return CommonConstants.NULL();
    }

    /**
     * 满足条件，操作并删除集合对象
     * tips：
     * 先执行自定义函数，再删除对象
     *
     * @param list      集合
     * @param predicate 判断函数
     * @param consumer  执行函数
     * @param <T>       泛型
     * @return 删除后的结果集
     */
    public static <T> List<T> removeIf(List<T> list, Predicate<? super T> predicate, Consumer<? super T> consumer) {
        list = filterNonNull(list);
        if (CollectionUtils.isEmpty(list)) {
            return emptyList();
        }

        list.removeIf(t -> {
            boolean flag = predicate.test(t);
            if (flag) {
                consumer.accept(t);
            }
            return flag;
        });
        return list;
    }

    /**
     * 按函数分组，并过滤重复对象
     *
     * @param list          集合
     * @param groupFunction 过滤函数
     * @param <T>           集合泛型
     * @param <K>           返回值泛型
     * @return 结果集
     */
    public static <T, K> List<T> filterRepeat(List<T> list, Function<? super T, ? extends K> groupFunction) {
        list = filter(list, t -> Objects.nonNull(t) && Objects.nonNull(groupFunction.apply(t)));
        if (CollectionUtils.isEmpty(list)) {
            return emptyList();
        }

        // 过滤重复数据
        List<T> newList = new ArrayList<>(list.size());
        Map<? extends K, List<T>> groupMap = group(list, groupFunction);

        groupMap.forEach((k, v) -> {
            if (v.size() > NumberUtils.INTEGER_ONE) {
                newList.add(singleObject(v));
            } else {
                newList.addAll(v);
            }
        });
        return newList;
    }

    /**
     * 忽略大小写的contains方法
     *
     * @param list 字符串集合
     * @param str  字符串
     * @return 结果
     */
    public static boolean containsIgnoreCase(List<String> list, String str) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }

        if (Objects.isNull(str)) {
            return list.stream().anyMatch(Objects::isNull);
        }

        return list.stream().anyMatch(t -> StringUtils.equalsIgnoreCase(t, str));
    }

    /**
     * 转为小写集合
     *
     * @param list 字符串集合
     * @return 结果集
     */
    public static List<String> toLowerCaseList(List<String> list) {
        return map(list, String::toLowerCase);
    }

    /**
     * 任意元素都不满足条件(集合为空返回true)
     *
     * @param list      集合
     * @param predicate 判断条件
     * @param <T>       泛型
     * @return 布尔值
     */
    public static <T> boolean noneMatch(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().noneMatch(predicate);
        }
        return true;
    }

    /**
     * 任意一个元素满足条件(集合为空返回false)
     *
     * @param list      集合
     * @param predicate 判断条件
     * @param <T>       泛型
     * @return 布尔值
     */
    public static <T> boolean anyMatch(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().anyMatch(predicate);
        }
        return false;
    }

    /**
     * 任意元素都满足条件(集合为空返回true)
     *
     * @param list      集合
     * @param predicate 判断条件
     * @param <T>       泛型
     * @return 布尔值
     */
    public static <T> boolean allMatch(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().allMatch(predicate);
        }
        return true;
    }

    /**
     * 集合遍历
     *
     * @param list   集合
     * @param action 遍历动作
     * @param <T>    泛型
     */
    public static <T> void forEach(List<T> list, Consumer<? super T> action) {
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(action);
        }
    }

    /**
     * 集合为空，则返回空集合
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 结果集
     */
    public static <T> List<T> emptyIfNull(List<T> list) {
        return Objects.isNull(list) ? emptyList() : list;
    }

    /**
     * 获取集合中重复的元素
     * <p>
     * tips:
     * 对象需重写hashCode方法
     *
     * @param list 集合
     * @param <T>  泛型
     * @return 结果集
     */
    public static <T> List<T> getDuplicateElements(List<T> list) {
        if (CollectionUtils.isEmpty(list)) {
            return emptyList();
        }

        Map<T, List<T>> groupMap = group(list, e -> e);
        List<List<T>> duplicates = filter(new ArrayList<>(groupMap.values()), t -> t.size() > NumberUtils.INTEGER_ONE);
        return map(duplicates, ListTools::singleObject);
    }

    /**
     * 根据条件，获取单个元素(optional版本)
     *
     * @param list      集合
     * @param predicate 条件函数
     * @param <T>       泛型
     * @return optional
     */
    public static <T> Optional<T> findOneOptional(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isEmpty(list)) {
            return Optional.empty();
        }

        return single(filter(list, predicate));
    }

    /**
     * 根据条件，获取单个元素
     *
     * @param list      集合
     * @param predicate 条件函数
     * @param <T>       泛型
     * @return 结果集
     */
    public static <T> T findOne(List<T> list, Predicate<? super T> predicate) {
        if (CollectionUtils.isEmpty(list)) {
            return CommonConstants.NULL();
        }

        return singleObject(filter(list, predicate));
    }

    /**
     * addAll方法
     *
     * @param targetList 目标集合
     * @param dataList   待添加的集合
     * @param <T>        泛型
     */
    public static <T> void addAll(List<T> targetList, List<T> dataList) {
        if (Objects.nonNull(targetList) && CollectionUtils.isNotEmpty(dataList)) {
            targetList.addAll(dataList);
        }
    }
}
